package org.iabako.server.serviceimpl.business;

import org.iabako.server.dao.JpaDAO;
import org.iabako.server.dao.business.QueryDefinitionDAO;
import org.iabako.server.serviceimpl.security.SessionUser;
import org.iabako.server.tools.BundleMessages;
import org.iabako.shared.entity.business.AbstractEntity;
import org.iabako.shared.entity.business.BusinessEntity;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.entity.user.User;
import org.iabako.shared.querydefinition.columndefinition.ColumnDefinition;
import org.iabako.shared.querydefinition.dto.QueryDefinitionDTO;
import org.iabako.shared.querydefinition.dto.QueryOperatorEnum;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;

/**
 * Created by jose on 22/03/14.
 */
public abstract class AbstractServiceImpl {

    @Autowired
    protected SessionUser sessionUser;
    @Autowired
    BundleMessages messages;
    @Autowired
    private QueryDefinitionDAO queryDefinitionDAO;

    protected abstract JpaDAO getDAO();

    @PostConstruct
    public void init() throws Exception {
    }

    @PreDestroy
    public void destroy() {
    }

    protected Enterprise getEnterpriseFromSessionUser() {
        try {
            return sessionUser != null && sessionUser.getUser() != null ? sessionUser.getUser().getEnterprise() : null;
        } catch (BeanCreationException exception) {
            return null;
        }
    }

    protected User getSessionUser() {
        try {
            return sessionUser != null ? sessionUser.getUser() : null;
        } catch (BeanCreationException exception) {
            return null;
        }
    }

    public String getNextAvailableId() {
        return getDAO().getNextAvailableId();
    }

    public AbstractEntity getById(Long id) {
        AbstractEntity entity = (AbstractEntity) getDAO().findById(id);
        if (entity != null) {
            entity.copyDatesAsString();
        }
        return entity;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public AbstractEntity save(AbstractEntity entity) {
        if (entity.getId() == null) {
            getDAO().persist(entity);
        } else {
            entity = (AbstractEntity) getDAO().merge(entity);
        }
        return entity;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean remove(Long id) {
        AbstractEntity abstractEntity = getById(id);
        return remove(abstractEntity);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean remove(AbstractEntity abstractEntity) {
        if (abstractEntity != null) {
            getDAO().remove(abstractEntity);
            return true;
        }
        return false;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean removeAll(QueryDefinitionDTO queryDefinitionDTO) {
        queryDefinitionDTO.setPageSize(-1);
        queryDefinitionDTO.excludeAllColumns();
        queryDefinitionDAO.executeQueryDefinition(queryDefinitionDTO);
        for (Long id : queryDefinitionDTO.getResults().keySet()) {
            remove(id);
        }
        return true;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveExternalLinkInfo(BusinessEntity businessEntity, String linkName, String linkUrl) {
        getDAO().saveExternalLinkInfo(businessEntity, linkName, linkUrl);
    }

    public QueryDefinitionDTO setSearchCriteriaFromSuggest(QueryDefinitionDTO qd, String suggestionValue, ColumnDefinition[] criteriaColumns) {
        if (GenericTools.isEmpty(suggestionValue)) {
            return qd;
        }

        for (ColumnDefinition c : criteriaColumns) {
            qd.addCriteriaOR(c, QueryOperatorEnum.LIKE, suggestionValue);
        }

        return qd;
    }

    protected void setBusinessTrackInfo(BusinessEntity businessEntity){
        Date today = new Date();
        if(businessEntity.getCreationDate() == null){
            businessEntity.setCreationDate(today);
        }
        businessEntity.setLastModificationDate(today);
        businessEntity.setLastModificationUser(getSessionUser());
    }
}
